package com.service.screenWeb.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.service.config.utils.IdUtil;
import com.service.config.utils.JsonXMLUtils;
import com.service.config.utils.ModelMapperUtil;
import com.service.config.utils.RedisUtil;
import com.service.screenWeb.dao.*;
import com.service.screenWeb.dto.ProgrammeInfoDto;
import com.service.screenWeb.dto.ProgrammeInfoViewDto;
import com.service.screenWeb.entity.*;
import com.service.screenWeb.service.ProgrammeInfoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.service.config.constant.Constant.USER_ASSEMBLY_INFO;
import static com.service.config.constant.Constant.USER_PROGRAMME_INFO;

/**
 * 方案信息表(ProgrammeInfo)表服务实现类
 *
 * @author makejava
 * @since 2021-05-18 19:56:24
 */
@Service("programmeInfoService")
public class ProgrammeInfoServiceImpl implements ProgrammeInfoService {
    @Resource
    private ProgrammeInfoDao programmeInfoDao;
    @Resource
    private AssemblyInfoDao assemblyInfoDao;
    @Resource
    private LayoutDao layoutDao;
    @Resource
    private AssemblyConfigureDao assemblyConfigureDao;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ProgrammeInfoViewDao programmeInfoViewDao;
    @Resource
    private VFilePhysicsInfoDao vFilePhysicsInfoDao;
    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ProgrammeInfo queryById(String id) {
        return this.programmeInfoDao.queryById(id);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<ProgrammeInfo> queryAllByLimit(int offset, int limit) {
        return this.programmeInfoDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param programmeInfo 实例对象
     * @return 实例对象
     */
    @Override
    public ProgrammeInfo insert(ProgrammeInfo programmeInfo) throws Exception {
        ProgrammeInfo programmeInfo1 = new ProgrammeInfo();
        programmeInfo1.setId(programmeInfo.getId());
        programmeInfo.setId(IdUtil.getStringId());
        String layoutInfo = programmeInfo.getLayoutInfo();
        JSONArray jsonArray = JSONArray.parseArray(layoutInfo);
        List<ProgrammeInfoViewDto> programmeInfoViewList = jsonArray.toJavaList(ProgrammeInfoViewDto.class);
        List<Layout> layoutList = new ArrayList<>();
        List<AssemblyConfigure> assemblyConfigureList = new ArrayList<>();
        getProgrammeInfoView(programmeInfo, programmeInfoViewList, assemblyConfigureList, programmeInfo, layoutList);
        ProgrammeInfo programmeInfo2 = programmeInfoDao.queryById(programmeInfo1.getId()); // 新增方案时把logo的id复制过来
        if (programmeInfo2 != null){
            if (programmeInfo2.getFileId() !=null && !programmeInfo2.getFileId().equals("")) {
                programmeInfo.setFileId(programmeInfo2.getFileId());
                programmeInfoDao.updateFileId(programmeInfo);
            }
        }
        return programmeInfo;
    }

    /**
     * 修改数据
     *
     * @param programmeInfo 实例对象
     * @return 实例对象
     */
    @Override
    public ProgrammeInfo update(ProgrammeInfo programmeInfo) {
        List<ProgrammeInfoViewDto> programmeInfoView = getProgrammeInfoView(programmeInfo);
        List<Layout> layoutList = new ArrayList<>();
        List<AssemblyConfigure> assemblyConfigureList = new ArrayList<>();
        for (ProgrammeInfoViewDto programmeInfoViewDto : programmeInfoView) {
            layoutList.add(updateLayoutInfo(programmeInfoViewDto,programmeInfo));
            assemblyConfigureList.add(updateAssemblyConfigInfo(programmeInfoViewDto,programmeInfo));
        }
        int programmeStatus = getProgrammeStatus(programmeInfo, false);
        int i = layoutDao.insertOrUpdateBatch(layoutList);
        assemblyConfigureDao.insertOrUpdateBatch(assemblyConfigureList);
        return this.queryById(programmeInfo.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    @Transactional
    public HashMap deleteById(String id) {
        ProgrammeInfo programmeInfo = programmeInfoDao.queryById(id);
        HashMap map = new HashMap();
        if (programmeInfo != null) {
            if (programmeInfo.getStatus()) {
                map.put("errorMsg","该方案为启用状态，不允许删除");
                return map ;
            }else {
                boolean b = this.programmeInfoDao.deleteById(id) > 0;
                layoutDao.deleteByProgrammeId(id);
                assemblyConfigureDao.deleteByProgrammeId(id);
                return null;
            }
        }
        map.put("errorMsg","该方案不存在，请刷新页面获取最新数据");
        return map;
    }

    /**
     * 查询加默认
     * @param programmeInfo
     * @param userId
     * @return
     * @throws Exception
     */
    @Override
    public List<ProgrammeInfoDto> queryAll(ProgrammeInfo programmeInfo, String userId) throws Exception {
        List<ProgrammeInfo> programmeInfoList = programmeInfoDao.queryAll(programmeInfo);
        if (programmeInfoList.size() > 0) {
            // 用户存在方案
            List<ProgrammeInfoDto> programmeInfoDtoList = ModelMapperUtil.strictMapList(programmeInfoList, ProgrammeInfoDto.class);
            programmeInfoDtoList.stream().forEach(programmeInfoDto -> {
                programmeInfoList.stream().forEach(programmeInfo1 -> {
                        if (programmeInfoDto.getId().equals(programmeInfo1.getId())) {
                        VFilePhysicsInfo vFilePhysicsInfo = new VFilePhysicsInfo();
                        JSONArray jsonArray = JSONArray.parseArray(programmeInfo1.getLayoutInfo());
                        if (programmeInfo1.getFileId() != null && !programmeInfo1.getFileId().equals(""))  {
                            vFilePhysicsInfo = vFilePhysicsInfoDao.queryById(programmeInfo1.getFileId());
                            programmeInfoDto.setFileUrl(vFilePhysicsInfo.getFileseverdomain()+vFilePhysicsInfo.getFiledicdomain()
                                    +"/"+vFilePhysicsInfo.getFilename());
                        }
                            List<ProgrammeInfoViewDto> programmeInfoViewList = new ArrayList<>();
                        if(jsonArray != null){
                            programmeInfoViewList = jsonArray.toJavaList(ProgrammeInfoViewDto.class);
                        }
                        programmeInfoDto.setProgrammeInfoViewList(programmeInfoViewList);
                    }
                });
            });

            return programmeInfoDtoList.stream().sorted(Comparator.comparing(ProgrammeInfoDto::getStatus).reversed()).collect(Collectors.toList());
        }
        List<ProgrammeInfo> programmeInfoList1 = programmeInfoDao.queryDefault();
        for (ProgrammeInfo programmeInfo1 : programmeInfoList1){
            if (programmeInfo1.getId().equals("9")) {
                programmeInfo = programmeInfo1;
            }
        }
        programmeInfo.setUserId(userId);
        programmeInfo.setId(IdUtil.getStringId());
        programmeInfo.setStatus(true);
        List<ProgrammeInfoViewDto> programmeInfoViewList = getProgrammeInfoView(programmeInfo);
        List<AssemblyConfigure> assemblyConfigureList = new ArrayList<>();
        ProgrammeInfo finalProgrammeInfo = programmeInfo;
        List<Layout> layoutList = new ArrayList<>();
        getProgrammeInfoView(programmeInfo, programmeInfoViewList, assemblyConfigureList, finalProgrammeInfo, layoutList);
        return queryAll(programmeInfo,userId);
    }

    /**
     * 获取默认方案
     * @return
     */
    @Override
    public List<ProgrammeInfoDto> queryDefault() {
        List<ProgrammeInfo> programmeInfoList = programmeInfoDao.queryDefault();
        List<ProgrammeInfoDto> programmeInfoDtoList = ModelMapperUtil.strictMapList(programmeInfoList, ProgrammeInfoDto.class);
        for (ProgrammeInfoDto programmeInfoDto : programmeInfoDtoList) {
            for (ProgrammeInfo programmeInfo : programmeInfoList ) {
                if (programmeInfoDto.getId().equals(programmeInfo.getId())) {
                    programmeInfoDto.setProgrammeInfoViewList(JSONArray.parseArray(programmeInfo.getLayoutInfo()).toJavaList(ProgrammeInfoViewDto.class));
                }
            }
        }
        Collections.sort(programmeInfoDtoList,new Comparator<ProgrammeInfoDto>() {
            @Override
            public int compare(ProgrammeInfoDto o1, ProgrammeInfoDto o2) {

                Long s = Long.parseLong(o1.getId());//由于从map里面取出来的值为Object类型，无法直接转换为Integer类型，需要转换为double
                Long d = Long.parseLong(o2.getId());
                //使用Entry类中的值来比较大小
                return s.compareTo(d);//s在前面是升序,s在后面是降序
            }

        });
        return programmeInfoDtoList;
    }

    /**
     * 应用该方案或关闭该方案
     * @param strictMap
     */
    @Override
    @Transactional
    public HashMap updateStatus(ProgrammeInfo strictMap) {
        HashMap map = new HashMap();
        if (strictMap.getStatus()) {
            List<ProgrammeInfo> programmeInfoList = programmeInfoDao.queryByUserId(strictMap.getUserId());
            programmeInfoList.stream().forEach(programmeInfo1 -> {
                programmeInfo1.setStatus(false);
            });
            programmeInfoList.add(strictMap);
            programmeInfoDao.updateStatus(programmeInfoList);
            return map;
        }else {
            map.put("errorMsg","参数status传输错误，请校验");
            return map;
        }
    }

    /**
     * 操作数据库
     * @param programmeInfo
     * @param programmeInfoViewList
     * @param assemblyConfigureList
     * @param finalProgrammeInfo
     * @param layoutList
     */
    @Transactional
    void getProgrammeInfoView(ProgrammeInfo programmeInfo, List<ProgrammeInfoViewDto> programmeInfoViewList, List<AssemblyConfigure> assemblyConfigureList, ProgrammeInfo finalProgrammeInfo, List<Layout> layoutList) throws Exception {
        programmeInfoViewList.stream().forEach(programmeInfoView -> {
            Layout layoutInfo1 = getLayoutInfo(finalProgrammeInfo, programmeInfoView);
            programmeInfoView.setLayoutId(layoutInfo1.getId());
            layoutList.add(layoutInfo1);
            AssemblyConfigure assemblyConfigInfo = getAssemblyConfigInfo(finalProgrammeInfo, programmeInfoView);
            programmeInfoView.setAssemblyConfigureId(assemblyConfigInfo.getId());
            assemblyConfigureList.add(assemblyConfigInfo);

        });
        programmeInfo.setLayoutInfo(JsonXMLUtils.obj2json(programmeInfoViewList));
        int programmeStatus = getProgrammeStatus(programmeInfo, true);
        if (programmeStatus > 0 ) {
            if (layoutList.size()>0) {
                 layoutDao.insertBatch(layoutList);
            }
            if (assemblyConfigureList.size() > 0) {
               assemblyConfigureDao.insertBatch(assemblyConfigureList);
            }
        }
    }
    private int getProgrammeStatus(ProgrammeInfo programmeInfo,Boolean flag) {
        int insertOrUpdate = 0;
        List<ProgrammeInfo> programmeInfoList = new ArrayList<>();
        if (programmeInfo.getStatus()) {
            programmeInfoList = programmeInfoDao.queryByUserId(programmeInfo.getUserId());
            programmeInfoList.stream().forEach(programmeInfo1 -> {
                programmeInfo1.setStatus(false);
            });
        }
        programmeInfoList.add(programmeInfo);
        insertOrUpdate = this.programmeInfoDao.insertOrUpdateBatch(programmeInfoList);
        return insertOrUpdate;
    }

    /**
     *  设置布局
     * @param finalProgrammeInfo
     * @param programmeInfoView
     * @return
     */
    private Layout getLayoutInfo(ProgrammeInfo finalProgrammeInfo, ProgrammeInfoViewDto programmeInfoView) {
        Layout layout = ModelMapperUtil.strictMap(programmeInfoView,Layout.class);
        layout.setId(IdUtil.getStringId());
        layout.setProgrammeId(finalProgrammeInfo.getId());
        layout.setUserId(finalProgrammeInfo.getUserId());
       return layout;
    }
    /**
     *  更新布局
     * @param programmeInfoView
     * @return
     */
    private Layout updateLayoutInfo(ProgrammeInfoViewDto programmeInfoView,ProgrammeInfo programmeInfo) {
        Layout layout = ModelMapperUtil.strictMap(programmeInfoView,Layout.class);
        layout.setId(programmeInfoView.getLayoutId());
        layout.setProgrammeId(programmeInfo.getId());
        return layout;
    }
    /**
     * 设置组件单独配置
     * @param finalProgrammeInfo
     * @param programmeInfoView
     * @return
     */
    private AssemblyConfigure getAssemblyConfigInfo(ProgrammeInfo finalProgrammeInfo, ProgrammeInfoViewDto programmeInfoView) {
        AssemblyConfigure assemblyConfigure = ModelMapperUtil.strictMap(programmeInfoView,AssemblyConfigure.class);
        assemblyConfigure.setId(IdUtil.getStringId());
        assemblyConfigure.setProgrammeId(finalProgrammeInfo.getId());
        assemblyConfigure.setUserId(finalProgrammeInfo.getUserId());
        return assemblyConfigure;
    }
    /**
     * 更新组件单独配置
     * @param programmeInfoView
     * @return
     */
    private AssemblyConfigure updateAssemblyConfigInfo(ProgrammeInfoViewDto programmeInfoView,ProgrammeInfo programmeInfo) {
        AssemblyConfigure assemblyConfigure = ModelMapperUtil.strictMap(programmeInfoView,AssemblyConfigure.class);
        assemblyConfigure.setId(programmeInfoView.getAssemblyConfigureId());
        assemblyConfigure.setProgrammeId(programmeInfo.getId());
        return assemblyConfigure;
    }

    /**
     * json转化
     * @param finalProgrammeInfo
     * @return
     */
    private List<ProgrammeInfoViewDto> getProgrammeInfoView(ProgrammeInfo finalProgrammeInfo) {
        String layoutInfo = finalProgrammeInfo.getLayoutInfo();
        JSONArray jsonArray = JSONArray.parseArray(layoutInfo);
        List<ProgrammeInfoViewDto> programmeInfoViewDtoList = jsonArray.toJavaList(ProgrammeInfoViewDto.class);
        programmeInfoViewDtoList.stream().forEach(programmeInfoViewDto -> {
            programmeInfoViewDto.setUserId(finalProgrammeInfo.getUserId());
        });
        return programmeInfoViewDtoList;
    }
}
